home *** CD-ROM | disk | FTP | other *** search
/ Aminet 52 / Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso / Aminet / misc / emu / Apex-src.lha / ED.XPL < prev    next >
Text File  |  2001-09-30  |  46KB  |  1,747 lines

  1. \ED.XPL        MAY-17-90    (Version 1.1; see HELP and INITIALIZE)
  2. \By Richard Ottosen and Loren Blaney
  3. \This is a version of VED/MRED written in XPL to run on the 68000.
  4. \
  5. \REVISION HISTORY:
  6. \ NOV-84, Original version, R.O.
  7. \ FEB-86, Modified for DFM Engineering, L.B.
  8. \ AUG-86, Fixed some bugs and added some enhancements, L.B.
  9. \ NOV-29-86, Added fast disk I/O, BLIT backwards, and fixed sliding cursor.
  10. \ DEC-04-86, Fixed restart to allow concatenating files, cleaned HELP menus.
  11. \ DEC-12-86, Fixed Close and N buffer search, L.B.
  12. \ MAR-11-87, Modified for the Amiga, L.B.
  13. \ APR-11-87, Changed string and BLIT conventions.
  14. \ JUL-06-88, Speed up screen display slightly, add mods for 24/48 line toggle.
  15. \ MAY-17-90, Fix margin command for last paragraph when not terminated by a CR.
  16. \
  17. \NOTES:
  18. \See HELP for the directions.
  19. \
  20. \Terminal-specific code is marked "%%%".
  21. \
  22. \This text editor is always in insert mode. Characters may be rapidly inserted
  23. \ because the text in the edit buffer is split at the point where the cursor
  24. \ is. Inserted characters are simply stored in the split -- the rest of the
  25. \ text does not need to be moved.
  26. \
  27. \If the screen looks like this:
  28. \
  29. \ The quick brown fox jumps over the lazy dog.
  30. \             ^
  31. \            Displayed cursor
  32. \
  33. \The edit buffer will look like this:
  34. \
  35. \ The quick brown fox jum................................ps over the lazy dog.
  36. \                 ^                 ^
  37. \                CINX                    C2INX
  38. \
  39. \If an "X" is inserted, the screen will look like this:
  40. \
  41. \ The quick brown fox jumXps over the lazy dog.
  42. \              ^
  43. \            Displayed cursor
  44. \
  45. \ and the edit buffer will look like this:
  46. \
  47. \ The quick brown fox jumX...............................ps over the lazy dog.
  48. \                  ^                 ^
  49. \                CINX                    C2INX
  50. \
  51. \When CINX = C2INX, the edit buffer is full and no more characters may be
  52. \ inserted.
  53.  
  54. code
  55. ABS=0,        RAN=1,        REM=2,        RESERVE=3,
  56. SWAP=4,        EXTEND=5,    RESTART=6,    CHIN=7,
  57. CHOUT=8,    CRLF=9,        INTIN=10,    INTOUT=11,
  58. TEXT=12,    OPENI=13,    OPENO=14,    CLOSE=15,
  59. ABORT=16,    \TRAP=17,\    FREE=18,    \GETERR=22,\    
  60. CURSOR=23,    BLIT=36,
  61. BUTES=124,    GETKEY=125,    KEYHIT=126,    SHOCUR=127;
  62.  
  63. ext    CHIN3=$C00,    CHOUT3=$C06;
  64.  
  65. def    CHKUSRF= $69C;        \flag to enable CTRL-C = abort, etc.
  66. def    PR=2, DISK=3;
  67.  
  68. def    CTRLA= $01,    CTRLB= $02,    CTRLC= $03,    CTRLD= $04,
  69.     CTRLE= $05,    CTRLF= $06,    CTRLG= $07,    CTRLH= $08,
  70.     CTRLI= $09,    CTRLJ= $0A,    CTRLK= $0B,    CTRLL= $0C,
  71.     CTRLM= $0D,    CTRLN= $0E,    CTRLO= $0F,    CTRLP= $10,
  72.     CTRLQ= $11,    CTRLR= $12,    CTRLS= $13,    CTRLT= $14,
  73.     CTRLU= $15,    CTRLV= $16,    CTRLW= $17,    CTRLX= $18,
  74.     CTRLY= $19,    CTRLZ= $1A,
  75.  
  76.     BEL= $07,    TAB= $09,    LF= $0A,    FF= $0C,    
  77.     CR= $0D,    EOF= $1A,    ESC= $1B,    DEL= $7F,    
  78.  
  79.     SP= $20,    \space char
  80.     SPIND= ^_,    \indicator for a space when showing control chars
  81.     WILDCH= CTRLW;    \wild character matches anything in a search
  82.  
  83. def    XBUFSIZ= 5000,    \scoop (X register) buffer size
  84.     PAD= XBUFSIZ,    \space left when reading in a file
  85.     COLMAX= 255,    \maximum possible column (with horz scrolling)
  86.     DBUFSIZ= 256;    \size of deferred command (line) buffer
  87.             \WARNING: status display assumes 80 columns and
  88.             \ HELP menus assume 24 lines
  89. def    CONWIDE= $69E, CONHIGH= $69F;    \SYSPAG parameters (screen size)
  90.  
  91. int    CINX,        \char position index (in text buffer)
  92.     C2INX,        \second char position index
  93.     SCINX,        \saved char pointers for OOPS command
  94.     SC2INX,
  95.     ACINX,        \auxillary cursor
  96.     DINX,        \array: index for command line buffer (points to end +1)
  97.     XINX,        \index for X register (scoop)
  98.     CHAR,        \holds character struck on keyboard
  99.     CURH,        \horizontal posn of cursor from last CR. This is COL:
  100.             \ on the status line, (0 through COLMAX).
  101.     CURL,        \line on the screen where the cursor is currently
  102.     CURLINE,    \screen line where the edit-buffer cursor appears
  103.     LEFTCOL,    \column number of the left-most displayed char
  104.             \ (= number of chars scrolled off of left edge)
  105.     RIGHTCOL,    \column number + 1 of the right-most displayed char
  106.     BUFSIZ,        \size of edit buffer (bytes)
  107.  
  108.     XFLAG,        \scoop (X reg) is enabled
  109.     EOFFLAG,    \EOF is read from input file
  110.     CLOSFLAG,    \output file has been closed
  111.     ERRFLAG,    \error flag used for terminating command-line loop
  112.  
  113.     DBUF,        \array of buffers: deferred command (line) buffer
  114.     DN,        \current DBUF [0-9]
  115.     REMAIN,        \remaining char space
  116.     II,        \scratch for MAIN
  117.     WIDTH,        \number of chars per line
  118.     HEIGHT;        \number of lines on the screen
  119.  
  120. reg addr BUFFER;    \main text buffer
  121.  
  122. addr    XBUF,        \scoop buffer (X register)
  123.     STATCOND,    \status condition message string (8 chars max)
  124.     TICKMARKS,    \ruler tick marks
  125.     SSTR,        \search string, must be global because of XPL bug
  126.     ADDR;        \used to access absolute addresses
  127.  
  128. int    PARAMS;        \initialization parameters (may be saved with program)
  129. def    \PARAMS\    \note: order must agree with constant array
  130.     COLDFLAG,    \true if not a restart
  131.     LEFTMARGIN,    \left margin column position
  132.     RIGHTMARGIN,    \right margin column position (last char is in this col)
  133.     BELLCOL,    \column for end-of-line bell
  134.     PARAINDENT,    \number of spaces to indent the beginning of paragraphs
  135.     S1FLAG,        \ignore upper/lower case in searches
  136.     S2FLAG,        \search backwards
  137.     SHOWFLAG;    \show the control chars
  138.  
  139. \----------------------------------------------------------------------
  140.  
  141. func    KEYIN;        \Get a character from the keyboard
  142. \Inputs: CURH, LEFTCOL.
  143. int    CHAR, H;
  144. begin
  145. H:= CURH -LEFTCOL;            \get the screen's position, [0-79]
  146. if H<0 then H:= 0;
  147. if H > WIDTH-1 then H:= WIDTH-1;
  148. CURSOR(H, CURL);
  149. SHOCUR(true);
  150.  
  151. repeat until KEYHIT;            \wait for a character
  152. CHAR:= GETKEY;
  153.  
  154. if CHAR>=$20 & CHAR<=$7E then        \echo printable characters immediately
  155.     [CHOUT(0,CHAR);
  156.     CURH:= CURH +1];    \anticipate the cursor position for fast typing
  157.  
  158. SHOCUR(false);
  159.  
  160. WIDTH:= ADDR(CONWIDE);            \set HEIGHT & WIDTH in case they changed
  161. HEIGHT:= ADDR(CONHIGH);
  162. CURLINE:= (HEIGHT -6);            \put cursor on 3rd line from bottom
  163.                     \ (in case HEIGHT changed)
  164. return CHAR;
  165. end;    \KEYIN
  166.  
  167. \----------------------------------------------------------------------
  168.  
  169. proc    HELP(DEV);    \Show/print HELP screen
  170. \(DON'T straighten up the text until you see what "^" does.)
  171. int    DEV;
  172. begin
  173. if DEV=0 ! DEV=1 then CHOUT(0,FF) else OPENO(DEV);
  174. TEXT(DEV,"ED, V1.1        -- IMMEDIATE COMMANDS --
  175.  
  176.     MOVE                    ADDITIONAL CHARACTERS
  177. ^^A  -  Ahead a character        ^^I  -  Tab
  178. ^^Q  -  Back a character            --> -  Indent Under line above (^^U)
  179. ^^N  -  Ahead to Next word        ^^L  -  Form feed (new page)
  180. ^^B  -  Back a word            ^^Z  -  Shift case and move ahead
  181. ^^S  -  Ahead a line            ^^T  -  Display control chars (on/off)
  182. ^^W  -  Back a line            ^^^^  -  Always insert next keystroke
  183. ^^J  -  Ahead a page (down arrow)
  184. ^^K  -  Back a page (up arrow)            SCOOP
  185. ^^D  -  Ahead to end of text buffer    ^^R  -  Start (or Resume) a scoop-up
  186. ^^E  -  Back to start of text buffer    ^^F  -  Finish a scoop-up
  187.                     ^^Y  -  Insert scoop and erase it
  188.  
  189.     DELETE                    COMMAND LINE
  190. <-- -  Back a character (^^H)        ESC -  Enter command-line mode
  191. ^^C  -  Back a word            ^^G  -  Re-execute command line (Go)
  192. ^^X  -  Back a line            ^^V  -  Copy command line into text
  193. ^^O  -  Undelete (Oops!)            ^^P  -  Select command line (0-9)
  194.                     ^^]  -  Change search case sensitivity
  195.                     ^^_  -  Reverse search direction
  196. (^^ = CTRL key)");
  197.  
  198. if DEV = 0 then
  199.     begin
  200.     CURSOR(0,HEIGHT-1);
  201.     TEXT(0,"                      (Press any key to continue)");
  202.         \(don't display this on the hardcopy)
  203.     CURL:= HEIGHT-1;   CURH:= 78;    \set cursor position for KEYIN
  204.     repeat until KEYIN;
  205.  
  206.     CHOUT(0,FF);
  207.     end
  208. else    begin                \DEV = 2, the printer
  209.     CRLF(DEV);
  210.     CRLF(DEV);
  211.     CRLF(DEV);
  212.     end;
  213.  
  214. TEXT(DEV,"            -- COMMAND-LINE COMMANDS --
  215.  
  216.     DELETE                    SEARCH
  217. D  -  Back a character            S  -  For string (^^W = wild)
  218. R  -  Rest of line            N  -  Entire file (N text buffers)
  219. E  -  Erase scoop
  220. Z  -  Zap back to last form feed        MISCELLANY
  221. K  -  Kill entire text buffer        /  -  List help summary on printer
  222.                     L  -  List text buffer on printer
  223.     INSERT                M  -  Margin (left, right) or (bell)
  224. I  -  String                Y  -  Center line
  225. X  -  Scoop                V  -  Copy text into command line
  226. H  -  Hex value                J  -  Re-execute command line (Jump)
  227.                     P  -  Execute any command line (0-9)
  228.     FILES                ESC - Command separator
  229. G  -  Get next text buffer        ESC ESC - Execute command line
  230. A  -  Append from input file
  231. W  -  Write to output file            QUIT
  232. O  -  Open input and output files    Q  -  Quit and save text
  233. C  -  Close output file            T  -  Terminate and discard text
  234. ");
  235. if DEV = 0 then
  236.     begin
  237.     CURSOR(0,HEIGHT-1);
  238.     TEXT(0,"                      (Press any key to continue)");
  239.         \(don't display this on the hardcopy)
  240.     CURL:= HEIGHT-1;   CURH:= 78;    \set cursor position for KEYIN
  241.     repeat until KEYIN;
  242.     end
  243. else    begin
  244.     CLOSE(DEV);
  245.     end;
  246. end;    \HELP
  247.  
  248. \----------------------------------------------------------------------
  249.  
  250. proc    SHOWRULER;    \Display a ruler
  251. \Inputs: LEFTCOL, RIGHTCOL, TICKMARKS
  252. int    I, AT, LM, RM, BL, IN;
  253. begin
  254. if KEYHIT then return;
  255. CURSOR(0,HEIGHT-3);            \output the ruler
  256. \show the relative position in the file
  257. AT:= WIDTH *CINX /( (BUFSIZ -(C2INX -CINX)) +1) + LEFTCOL;
  258. LM:= PARAMS(LEFTMARGIN);
  259. RM:= PARAMS(RIGHTMARGIN);
  260. BL:= PARAMS(BELLCOL);
  261. IN:= PARAMS(PARAINDENT) +LM;
  262. for I:= LEFTCOL, RIGHTCOL-1 do
  263.     begin
  264.     case I of
  265.      AT:    CHOUT(0,$7F);        \%%%
  266.      BL:    CHOUT(0,^^);
  267.      IN:    CHOUT(0,^/);
  268.      LM,RM:    CHOUT(0,^|)
  269.     other CHOUT(0,TICKMARKS(I));
  270.     end;
  271. end;    \SHOWRULER
  272.  
  273. \----------------------------------------------------------------------
  274.  
  275. proc    SHOWCMDLINE;    \Display the command line (DBUF, up to DINX)
  276. \Inputs:  DINX, DBUF, DN.
  277. \Outputs: CURH, CURL.
  278. reg int    I, H;
  279. begin
  280. if KEYHIT then return;
  281. H:=0;
  282. CURSOR(0, HEIGHT-2);
  283. for I:= 0, DINX(DN)-1 do
  284.     begin
  285.     if DBUF(DN,I) < $20 then
  286.         begin
  287.         CHOUT(0, ^^);        \convert BEL to "^G", etc.
  288.         CHOUT(0, DBUF(DN,I)+$40);
  289.         H:= H +1;
  290.         end
  291.     else    CHOUT(0, DBUF(DN,I));
  292.     H:= H +1;
  293.     end;
  294.  
  295. CURH:= H;   CURL:= HEIGHT-2;        \tell KEYIN where the cursor is
  296.                     \ (kludge to help ENTERCMDLINE)
  297. if KEYHIT then return;
  298. while H<WIDTH do            \blank rest of command line
  299.     begin
  300.     CHOUT(0,SP);
  301.     H:= H +1;
  302.     end;
  303. end;    \SHOWCMDLINE
  304.  
  305. \----------------------------------------------------------------------
  306.  
  307. proc    SHOWSTATUS;    \Display the status line at the bottom of the screen
  308. \illegal?   CMD: 0   SCOOP: 2000   S # s -->   REM: 12345   AT: 12345   COL: 123
  309. \WARNINGS: This routine assumes an 80-column screen.
  310. \ If "CMD:" is moved then SELCMD should also be changed.
  311. \Inputs: CINX, C2INX, CURH, DN, XINX, STATCOND.
  312. reg int    I, CH;
  313.  
  314.     proc    NUMOUT(NUM, SIZE);
  315.     \Display a left-justified number in a field represented by SIZE
  316.     \I.e: a 3-digit field is represented by SIZE = 100.
  317.     int    NUM, SIZE;
  318.     begin
  319.     INTOUT(0,NUM);
  320.     if NUM=0 then NUM:=1;
  321.     while SIZE > NUM do
  322.         [CHOUT(0,SP);
  323.         NUM:= NUM *10];
  324.     end;    \NUMOUT
  325.  
  326.  
  327. begin    \SHOWSTATUS
  328. CURSOR(0,HEIGHT-1);
  329. if KEYHIT then return;
  330. loop for I:= 0, 8 do            \show status message, make sure old
  331.     [CH:= STATCOND(I);        \ message is erased, and don't flicker
  332.     if CH=0 ! I=8 then quit;
  333.     CHOUT(0, CH)];
  334. for I:= I, 10 do CHOUT(0, SP);
  335.  
  336. TEXT(0,"CMD: ");
  337. if KEYHIT then return;
  338. NUMOUT(DN, 1000);
  339. if KEYHIT then return;
  340.  
  341. TEXT(0,"SCOOP: ");
  342. if KEYHIT then return;
  343. NUMOUT(XBUFSIZ-XINX, 1000000);
  344. if KEYHIT then return;
  345.  
  346. if WIDTH =40 then return;
  347.  
  348. TEXT(0,"S ");
  349. CHOUT(0,if PARAMS(S1FLAG) then ^= else ^#);
  350. if KEYHIT then return;
  351. TEXT(0,if PARAMS(S2FLAG) then " s <--   " else " s -->   ");
  352. if KEYHIT then return;
  353.  
  354. TEXT(0,"REM: ");
  355. if KEYHIT then return;
  356. NUMOUT(C2INX -CINX, 10000000);
  357. if KEYHIT then return;
  358.  
  359. TEXT(0,"AT: ");
  360. if KEYHIT then return;
  361. NUMOUT(CINX, 10000000);
  362. if KEYHIT then return;
  363.  
  364. TEXT(0,"COL: ");
  365. if KEYHIT then return;
  366. NUMOUT(CURH, 100);
  367. end;    \SHOWSTATUS
  368.  
  369. \----------------------------------------------------------------------
  370.  
  371. proc    DISPLAY;    \Display the edit buffer for current cursor position
  372. \Inputs:  SHOWFLAG, CINX, C2INX, CURLINE
  373. \Outputs: LEFTCOL, RIGHTCOL, CURH, CURL
  374. int    I,        \scratch
  375.     CLINE,        \index to the start of a line
  376.     L;        \line counter
  377. reg int    C,        \scratch index into text buffer
  378.     H;        \horz. posn. from last carriage return (as displayed)
  379.  
  380.  
  381.     proc    DISPCHAR;    \Display an edit-buffer character
  382.     \Inputs: C, H, L;    DEL ($7F) may not be displayed by the H/W
  383.     int    CH;
  384.  
  385.         proc    DISPX(CH);
  386.         int    CH;
  387.         begin
  388.         if H >=LEFTCOL & H<RIGHTCOL then    \it is visible
  389.             CHOUT(0,CH);
  390.         H:= H+1;                \bump horz. posn.
  391.         end;    \DISPX
  392.  
  393.  
  394.     begin    \DISPCHAR
  395.     CH:= BUFFER(C);            \get char from buffer
  396.     C:= C+1;
  397.  
  398.     if CH>=$21 then
  399.         begin            \handle most characters
  400.         if H >=LEFTCOL & H<RIGHTCOL then    \it is visible
  401.             CHOUT(0,CH);            \DISPX inlined for speed
  402.         H:= H+1;                \bump horz. posn.
  403.         end
  404.     else    begin
  405.         if PARAMS(SHOWFLAG) then    \show normally hidden CTRL chars
  406.             begin
  407.             if CH = SP then DISPX(SPIND)
  408.             else    begin
  409.                 DISPX(^^);    \convert BEL into "^G", etc.
  410.                 DISPX(CH+$40);
  411.                 end;
  412.             end
  413.         else    begin
  414.             if CH = SP then DISPX(SP)
  415.             else if CH = TAB then
  416.                 repeat DISPX(SP) until (H & $0007) = 0;
  417.             end;
  418.  
  419.         if CH = CR then            \blank rest of the line
  420.             begin
  421.             while H < RIGHTCOL do    \fill out line with spaces
  422.                 begin
  423.                 if H >=LEFTCOL then CHOUT(0,SP);
  424.                 H:= H+1;    \bump horz. posn.
  425.                 end;
  426.             L:= L+1;        \new line
  427.             H:= 0;
  428.             end;
  429.         end;
  430.     end;    \DISPCHAR
  431.  
  432.  
  433. begin    \DISPLAY
  434. \Find out how much horizontal scroll (LEFTCOL) is needed (this is complicated
  435. \ because of tabs):
  436. C:= CINX;                \move C to the start of the line
  437. while BUFFER(C-1)#CR & C>0 do C:= C-1;
  438. CLINE:= C;                \save the start of this line
  439.  
  440. \Move forward to the cursor and count the displayed characters (H) along the way:
  441. H:= 0;
  442. for I:= CLINE, CINX-1 do
  443.     begin
  444.     H:= H +1;
  445.     if BUFFER(I) < $20 then
  446.         if PARAMS(SHOWFLAG) then H:= H +1    \count the "^"
  447.         else     if BUFFER(I) = TAB then
  448.                 H:= (H + 7) & $FFF8    \move to next tab stop
  449.             else H:= H -1;        \don't count hidden CTRL chars
  450.     end;
  451. LEFTCOL:= H - WIDTH + 1;        \(if H < WIDTH then LEFTCOL = 0)
  452. if LEFTCOL < 0 then LEFTCOL:= 0;
  453. RIGHTCOL:= WIDTH + LEFTCOL;        \right-most displayed column + 1
  454. if RIGHTCOL>COLMAX then
  455.     [RIGHTCOL:=COLMAX;   LEFTCOL:= RIGHTCOL - WIDTH];
  456.  
  457. CURH:= H;   CURL:=CURLINE;        \tell KEYIN where the cursor is
  458. if CURH = PARAMS(BELLCOL) then CHOUT(0,BEL);
  459.  
  460. \Display the line we are on (the cursor line) up to the cursor:
  461. CURSOR(0,CURLINE);
  462. H:= 0;
  463. L:= CURLINE;
  464. while C<CINX & not KEYHIT do DISPCHAR;    \(beware of very long lines)
  465.  
  466. \Simply display the cursor as a block for now, and we'll fix it up later.
  467. \ (We must do this because 38.4kb is very S-L-O-W...)
  468. \First, make sure we're there (beware of fast typers).
  469. CURSOR(if CURH<WIDTH then CURH else WIDTH-1, CURL);
  470. C:= C2INX;                \first, show the character (in case
  471. if C<BUFSIZ then DISPCHAR        \ it's a control character)
  472. else H:= H +1;                \leave room for the cursor block
  473. \Move back and display a temporary block character:
  474. CURSOR(if CURH<WIDTH then CURH else WIDTH-1, CURL);
  475. CHOUT(0,$7F);                \ %%%
  476. \Resume displaying rest of line:
  477. if H<WIDTH then CURSOR(H, L) else CURSOR(0, L+1);
  478.  
  479. \Display the rest of the text from the cursor down to the bottom of the screen:
  480. while C<BUFSIZ & L<(HEIGHT-3) & not KEYHIT do DISPCHAR;
  481.  
  482. \If we're at the end of the buffer then fill out the rest of the display
  483. \ with spaces:
  484. while  L<(HEIGHT-3) & not KEYHIT do
  485.     begin
  486.     if H >=LEFTCOL & H<RIGHTCOL then CHOUT(0,SP);
  487.     H:= H+1;
  488.     if H>=RIGHTCOL then [H:=LEFTCOL;   L:=L+1];
  489.     end;
  490.  
  491. SHOWRULER;            \(inputs LEFTCOL from DISPLAY)
  492. SHOWSTATUS;
  493.  
  494. \Display lines from the line above the line the cursor is on up to the top
  495. \ of the screen:
  496. L:=CURLINE;
  497. while CLINE>0 & L>0 & not KEYHIT do
  498.     begin
  499.     C:= CLINE;            \move C to the start of the line
  500.     if C>0 then C:=C-1;        \back over the CR
  501.     while BUFFER(C-1)#CR & C>0 do C:= C-1;    \back up a line
  502.     CLINE:= C;
  503.  
  504.     L:= L-1;            \display the line
  505.     CURSOR(0,L);
  506.     H:= 0;
  507.     loop    begin
  508.         if BUFFER(C)=CR ! KEYHIT then [DISPCHAR;   quit];
  509.         DISPCHAR;
  510.         end;
  511.     L:= L-1;            \undo next line from DISPCHAR
  512.     end;
  513.  
  514. \Fill out the top of the screen with blank lines if necessary:
  515. while L>0 & not KEYHIT do
  516.     begin
  517.     L:= L-1;
  518.     CURSOR(0,L);
  519.     H:= 0;
  520.     while H < RIGHTCOL do
  521.         begin
  522.         if H >=LEFTCOL then CHOUT(0,SP);
  523.         H:= H+1;
  524.         end;
  525.     end;
  526.  
  527. \Replace the block with the character under the cursor:
  528. C:= C2INX;
  529. H:= CURH;
  530. CURSOR(if CURH<WIDTH then CURH else WIDTH-1, CURL);
  531. if C<BUFSIZ then DISPCHAR;
  532. end;    \DISPLAY
  533.  
  534. \----------------------------------------------------------------------
  535.  
  536. proc    SETSTAT(STR, FLAG);    \Set status condition
  537. addr    STR, FLAG;        \STR may have 8 characters maximum
  538. \Inputs:  ERRFLAG.
  539. \Outputs: STATCOND, ERRFLAG.
  540. begin
  541. if not ERRFLAG ! not FLAG then    \don't set condition if we already have
  542.     begin            \ an error -- only clear it
  543.     STATCOND:= STR;
  544.     ERRFLAG:= FLAG;
  545.     end;
  546. end;    \SETSTAT
  547.  
  548. \========================== BASIC COMMANDS ==============================\
  549.  
  550. proc    SAVEPTRS;    \Save edit-buffer pointers in case he screws up.
  551. \Deleted characters reside in the gap and they may be restored simply by
  552. \ restoring the edit pointers. These pointers are saved whenever a command,
  553. \ such as a cursor move, messes up the gap.
  554. begin
  555. SCINX:= CINX;
  556. SC2INX:= C2INX;
  557. end;    \SAVEPTRS
  558.  
  559.  
  560.  
  561. proc    OOPS;        \undo previous deletes (you can also undo this command)
  562. int    T;
  563. begin
  564. if CINX # SCINX ! C2INX#SC2INX then
  565.     begin
  566.     T:=CINX;   CINX:=SCINX;   SCINX:=T;    \swap CINX and SCINX
  567.     T:=C2INX;   C2INX:=SC2INX;   SC2INX:=T;    \swap C2INX and SC2INX
  568.     end
  569. else SETSTAT("nothing?",true);
  570. end;    \OOPS
  571.  
  572.  
  573.  
  574. proc    INSERT(CHAR);    \Insert a char into the edit buffer
  575. int    CHAR;
  576. begin
  577. if CINX <C2INX then            \if there's room...
  578.     begin
  579.     BUFFER(CINX):= CHAR;
  580.     CINX:= CINX+1;
  581. \    if ACINX >= CINX then ACINX:= ACINX +1;
  582.     SAVEPTRS;
  583.     end
  584. else SETSTAT("full?",true);
  585. end;    \INSERT
  586.  
  587. \----------------------------------------------------------------------
  588.  
  589. proc    DELCHAR;    \Delete back one char
  590. begin
  591. if CINX>0 then
  592.     begin
  593.     CINX:= CINX-1;
  594.     if XFLAG then            \scoop-up buffer is on
  595.         begin
  596.         if XINX<XBUFSIZ then
  597.             begin
  598.             XBUF(XINX):= BUFFER(CINX);
  599.             XINX:= XINX+1;
  600.             end
  601.         else    begin
  602.             SETSTAT("full?",true);
  603.             CINX:= CINX+1;    \delete failed, undo it
  604.             end;
  605.         end
  606.     end
  607. else SETSTAT("start?",true);
  608. end;    \DELCHAR
  609.  
  610.  
  611.  
  612. proc    DELWORD;    \Delete back one word
  613. int    CH;
  614. begin
  615. repeat    DELCHAR;            \delete all word separators
  616.     CH:=BUFFER(CINX);
  617. until CH#CR & CH#SP & CH#TAB ! ERRFLAG;
  618.  
  619. loop    begin                \delete the word
  620.     CH:=BUFFER(CINX-1);
  621.     if CH=CR ! CH=SP ! CH=TAB ! ERRFLAG then quit;
  622.     DELCHAR;
  623.     if CINX = 0 then quit;
  624.     end;
  625. end;    \DELWORD
  626.  
  627.  
  628.  
  629. proc    DELLINE;    \Delete back one line
  630. begin
  631. repeat DELCHAR until BUFFER(CINX-1)=CR ! CINX=0 ! ERRFLAG;
  632. end;    \DELLINE            (ERRFLAG? because XREG may be full)
  633.  
  634.  
  635.  
  636. proc    DELALL;        \Delete the entire edit buffer (kill)
  637. begin            \Notice that the scoop is not used here.
  638. CINX:=0;
  639. C2INX:=BUFSIZ;
  640. end;    \DELALL
  641.  
  642.  
  643.  
  644. proc    ZAP;        \Delete back to previous form feed or start
  645. begin            \ (the form feed is not deleted)
  646. repeat DELCHAR until BUFFER(CINX-1)=FF ! CINX=0 ! ERRFLAG;
  647. end;    \ZAP
  648.  
  649. \----------------------------------------------------------------------
  650.  
  651. proc    BACKCHAR;    \Move back one char in buffer
  652. begin
  653. DELCHAR;                \Move CINX back, checking for XREG, etc.
  654. if not ERRFLAG then            \if the delete succeeded then...
  655.     begin
  656.     C2INX:= C2INX-1;
  657.     BUFFER(C2INX):= BUFFER(CINX);
  658.     SAVEPTRS;
  659.     end;
  660. end;    \BACKCHAR
  661.  
  662.  
  663.  
  664. proc    BACKWORD;
  665. \Move back to the start of the current word or the previous word
  666. int    CH;
  667. begin
  668. repeat    BACKCHAR;            \back over all word separators
  669.     CH:=BUFFER(CINX);
  670. until CH#CR & CH#SP & CH#TAB ! ERRFLAG;
  671.  
  672. loop    begin
  673.     CH:=BUFFER(CINX-1);
  674.     if CH=CR ! CH=SP ! CH=TAB ! ERRFLAG then quit;
  675.     BACKCHAR;
  676.     if CINX = 0 then quit;
  677.     end;
  678. end;    \BACKWORD
  679.  
  680.  
  681.  
  682. proc    BACKLINE;
  683. \Move back to the start of the current line or the previous line
  684. begin
  685. repeat BACKCHAR until BUFFER(CINX-1)=CR ! CINX=0 ! ERRFLAG;
  686. end;    \BACKLINE
  687.  
  688.  
  689.  
  690. proc    BACKPAGE;    \Move backward one page
  691. int    I;
  692. begin
  693. if BUFFER(CINX-1) # CR then BACKLINE;
  694. for I:=1,HEIGHT-3 do BACKLINE;
  695. end;    \BACKPAGE
  696.  
  697.  
  698.  
  699. proc    BACKALL;    \Move to the beginning of buffer
  700. begin
  701. if XFLAG then repeat BACKCHAR until CINX=0 ! ERRFLAG
  702. else    begin
  703.     BLIT(BUFFER, BUFFER +C2INX -CINX, CINX);
  704.     C2INX:= C2INX - CINX;
  705.     CINX:= 0;
  706.     end;
  707. end;    \BACKALL
  708.  
  709. \----------------------------------------------------------------------
  710.  
  711. proc    FWDCHAR;    \Move forward one char in buffer
  712. begin
  713. if C2INX<BUFSIZ then
  714.     begin
  715.     BUFFER(CINX):= BUFFER(C2INX);
  716.     CINX:= CINX+1;   C2INX:= C2INX+1;
  717.     if XFLAG then
  718.         if XINX>0 then XINX:= XINX-1
  719.         else XFLAG:=false;
  720.     SAVEPTRS;
  721.     end
  722. else SETSTAT("end?",true);
  723. end;    \FWDCHAR
  724.  
  725.  
  726.  
  727. proc    FWDWORD;    \Move to the start of the next word
  728. \Note: This routine gives an error when moving to an EOF (not just beyond it)
  729. int    CH;
  730. begin
  731. repeat    FWDCHAR;            \Move forward to word separator
  732.     CH:=BUFFER(C2INX);
  733. until CH=CR ! CH=SP ! CH=TAB ! ERRFLAG;
  734.  
  735. repeat    FWDCHAR;            \Move forward to non-word separator
  736.     CH:=BUFFER(C2INX);
  737. until CH#CR & CH#SP & CH#TAB ! ERRFLAG;
  738. end;    \FWDWORD
  739.  
  740.  
  741.  
  742. proc    FWDLINE;    \Move to the start of the next line
  743. begin
  744. repeat    FWDCHAR;
  745. until BUFFER(CINX-1)=CR ! ERRFLAG;
  746. end;    \FWDLINE
  747.  
  748.  
  749.  
  750. proc    FWDPAGE;    \Move forward one page
  751. int    I;
  752. begin
  753. for I:=1,HEIGHT-3 do FWDLINE;
  754. end;    \FWDPAGE
  755.  
  756.  
  757.  
  758. proc    FWDALL;        \Move to the end of buffer
  759. int    I;
  760. begin
  761. if XFLAG then                \If the X reg was on, it's gone now
  762.     [XINX:=0;   XFLAG:=false];
  763. BLIT(BUFFER +C2INX, BUFFER +CINX, BUFSIZ -C2INX);
  764. CINX:= CINX + BUFSIZ - C2INX;
  765. C2INX:= BUFSIZ;
  766. SAVEPTRS;
  767. end;    \FWDALL
  768.  
  769.  
  770.  
  771. proc    SWAPCURSORS;    \Swap cursor with auxillary cursor
  772. int    I, T;
  773. begin
  774. if XFLAG then                \If the X reg was on, it's gone now
  775.     [XINX:=0;   XFLAG:=false];
  776.  
  777. \Move from current cursor position to auxillary cursor position:
  778. if ACINX > CINX then            \Move cursor forward
  779.     BLIT(BUFFER +C2INX, BUFFER +CINX, ACINX -CINX)
  780. else                    \Move cursor backward
  781.     for I:= 1, CINX -ACINX do
  782.         BUFFER(C2INX-I):= BUFFER(CINX-I);
  783.  
  784. T:= ACINX;   CINX:= ACINX;   ACINX:= T;    \swap primary and auxillary cursors
  785. SAVEPTRS;
  786. end;    \SWAPCURSORS
  787.  
  788. \----------------------------------------------------------------------
  789.  
  790. proc    DELREST;    \Delete the rest of a line
  791. begin
  792. loop    begin
  793.     if C2INX < BUFSIZ then C2INX:= C2INX +1
  794.     else [SETSTAT("end?", true);   quit];
  795.     if BUFFER(C2INX-1) = CR then quit;
  796.     end;
  797. end;    \DELREST
  798.  
  799.  
  800.  
  801. proc    FLIPCASE;
  802. \Flip the case of the letter at the cursor and move forward
  803. int    CH;
  804. begin
  805. CH:=BUFFER(C2INX);
  806. if C2INX<BUFSIZ & ((CH>=^A & CH<=^Z) ! (CH>=^a & CH<=^z)) then
  807.     begin
  808.     CH:= CH + (if CH >=^a then -$20 else $20);
  809.     BUFFER(C2INX):=CH;
  810.     FWDCHAR;
  811.     end
  812. else    begin
  813.     FWDCHAR;
  814.     SETSTAT("letter?",true);
  815.     end;
  816. end;    \FLIPCASE
  817.  
  818.  
  819.  
  820. proc    LIST;        \List edit buffer on printer
  821. int    C, CH;
  822. begin
  823. OPENO(PR);
  824. FWDALL;
  825. C:= 0;
  826. while C < CINX do
  827.     begin
  828.     CH:= BUFFER(C);
  829.     C:= C+1;
  830.  
  831.     if CH>=$21 then CHOUT(PR,CH)        \Handle most characters
  832.     else    begin
  833.         if PARAMS(SHOWFLAG) then    \show normally hidden ctrl chars
  834.             begin
  835.             if CH = SP then CHOUT(PR,SPIND)
  836.             else    begin
  837.                 CHOUT(PR,^^);    \convert BEL into "^G", etc.
  838.                 CHOUT(PR,CH+$40);
  839.                 end;
  840.             if CH = CR then CHOUT(PR,CH);
  841.             end
  842.         else    CHOUT(PR,CH);
  843.         end;
  844.     end;
  845. CRLF(PR);                \do not close because of form feed
  846. end;    \LIST
  847.  
  848. \----------------------------------------------------------------------
  849.  
  850. proc    XON;        \Turn on scoop (X reg)
  851. begin
  852. XFLAG:= true;
  853. SETSTAT("scoop",false);            \(Show it right away)
  854. end;    \XON
  855.  
  856.  
  857.  
  858. proc    XOFF;        \Turn off scoop (X reg)
  859. begin
  860. XFLAG:= false;
  861. SETSTAT("ok",false);            \(Show it right away)
  862. end;    \XOFF
  863.  
  864.  
  865.  
  866. proc    COPYX;        \Copy scoop (X reg) into the edit buffer
  867. \Note that the order of the text in XREG is backwards.
  868. int    X;
  869. begin
  870. XFLAG:=false;                \Make sure it's off
  871. X:= XINX;
  872. while X >0 do
  873.     begin
  874.     X:= X-1;
  875.     INSERT(XBUF(X));
  876.     end;
  877. end;    \COPYX
  878.  
  879. \----------------------------------------------------------------------
  880.  
  881. func    INHEX(D);    \Insert literal hex value
  882. int    D;
  883. int    H;
  884.  
  885.  
  886.     func    HEX(CH);    \Return the hex value
  887.     int    CH;        \hex digit in ASCII
  888.     begin
  889.     case of
  890.       CH>=^0 & CH<=^9:    return CH-$30;
  891.       CH>=^A & CH<=^F:    return CH-$37;
  892.       CH>=^a & CH<=^f:    return CH-$57
  893.     other SETSTAT("hex?",true);
  894.     end;    \HEX
  895.  
  896.  
  897. begin    \INHEX
  898. H:= HEX(DBUF(DN,D));
  899. H:= H*$10 + HEX(DBUF(DN,D+1));
  900. if not ERRFLAG then INSERT(H);
  901.  
  902. return D +2;                \Return index to next command
  903. end;    \INHEX
  904.  
  905.  
  906.  
  907. func    INSTRING(D);    \Insert a string
  908. int    D;        \Index into DBUF points to string
  909. int    CH;
  910. begin
  911. loop    begin
  912.     CH:= DBUF(DN,D);
  913.     if CH = ESC then return D;    \Return index to next command
  914.     INSERT(CH);
  915.     D:= D +1;
  916.     end;
  917. end;    \INSTRING
  918.  
  919. \----------------------------------------------------------------------
  920.  
  921. func    SEARCH(D);    \Forward search edit buffer for string.
  922. int    D;        \Index of first string character on command line (DBUF)
  923.             \Returns index to next command (failed or not)
  924. \Inputs: DBUF, DN, CINX, C2INX
  925. int    CH1, S1F;
  926. reg int    I, C;
  927.  
  928.  
  929. func    LOWER(CH);    \Shift to lowercase if PARAMS(S1FLAG) is true
  930. int    CH;
  931. begin
  932. if S1F then
  933.     if CH>=^A & CH<=^Z then
  934.         return CH ! $20;
  935. return CH;
  936. end;    \LOWER
  937.  
  938.  
  939.  
  940. proc    FWDSEARCH;    \Forward search edit buffer for string.
  941. begin
  942. C:= C2INX;                \start searching from the cursor
  943. I:= 0;                    \point to first char in string
  944. loop    begin
  945.     case SSTR(I) of
  946.       WILDCH, LOWER(BUFFER(C+I)):
  947.         begin            \it matches
  948.         I:= I+1;        \try next string character
  949.         if SSTR(I) = ESC then    \the entire string matches
  950.             begin
  951.             C:= C +I;        \point to end of string
  952.             if C > BUFSIZ then    \(ignore garbage beyond buffer)
  953.                 [SETSTAT("none?",true);   quit];
  954.  
  955.             \Move cursor forward to end of matching string:
  956.             BLIT(BUFFER +C2INX, BUFFER +CINX, C -C2INX);
  957.             CINX:= CINX + C -C2INX;
  958.             C2INX:=C;
  959.             SAVEPTRS;
  960.             quit;
  961.             end;
  962.         end
  963.     other    begin            \it doesn't match
  964.         C:= C +1;        \move forward in edit buffer
  965.         if C >= BUFSIZ then    \all done? then not found
  966.             [SETSTAT("none?",true);   quit];
  967.  
  968.         \Fast scan for first character (CH1):
  969.         \Wild characters are ignored
  970.         loop    begin
  971.             if S1F then    \if s = S then
  972.                 for C:= C, BUFSIZ do
  973.                 [if (BUFFER(C) ! $20) = CH1 then quit]
  974.                 \(good candidate -- it's rechecked above)
  975.             else
  976.                 for C:= C, BUFSIZ do
  977.                 if BUFFER(C) = CH1 then quit;
  978.             quit;        \quit if end of buffer
  979.             end;
  980.  
  981.         I:= 0;            \point to first char in string
  982.         end;
  983.     end;    \LOOP
  984. end;    \FWDSEARCH
  985.  
  986.  
  987.  
  988. proc    BACKSEARCH;    \Backward search edit buffer for string.
  989. begin
  990. C:= CINX -I -1;            \searching from the cursor - string length -1
  991. I:= 0;                    \point to first char in string
  992. loop    begin
  993.     case SSTR(I) of
  994.       WILDCH, LOWER(BUFFER(C+I)):
  995.         begin            \it matches
  996.         I:= I+1;        \try next string character
  997.         if SSTR(I) = ESC then    \the entire string matches
  998.             begin
  999.             if C < 0 then    \(ignore garbage in front of buffer)
  1000.                 [SETSTAT("none?",true);   quit];
  1001.             C:= C +I;        \point to end of string
  1002.  
  1003.             \Move cursor backward to end of matching string:
  1004.             BLIT(BUFFER+C, BUFFER+C2INX-(CINX-C), CINX-C);
  1005.  
  1006.             C2INX:= C2INX -(CINX -C);
  1007.             CINX:= CINX -(CINX -C);
  1008.             SAVEPTRS;
  1009.             quit;
  1010.             end;
  1011.         end
  1012.     other    begin            \it doesn't match
  1013.         C:= C -1;        \move backward in edit buffer
  1014.         if C < 0 then        \all done? then not found
  1015.             [SETSTAT("none?",true);   quit];
  1016.  
  1017.         \Fast scan for first character (CH1):
  1018.         \Wild characters are ignored
  1019.         \-C is a trick to fake: "for C:= C downto 0"
  1020.         loop    begin
  1021.             if S1F then    \if s = S then
  1022.                 for C:= -C, 0 do
  1023.                 [if (BUFFER(-C) ! $20) = CH1 then quit]
  1024.                 \(good candidate -- it's rechecked above)
  1025.             else
  1026.                 for C:= -C, 0 do
  1027.                 if BUFFER(-C) = CH1 then quit;
  1028.             quit;        \quit if start of buffer
  1029.             end;
  1030.         C:= -C;            \get positive C
  1031.         I:= 0;            \point to first char in string
  1032.         end;
  1033.     end;    \LOOP
  1034. end;    \BACKSEARCH
  1035.  
  1036.  
  1037.  
  1038. begin    \SEARCH
  1039. S1F:= PARAMS(S1FLAG);
  1040. I:=0;
  1041. loop    begin
  1042.     SSTR(I):= LOWER(DBUF(DN,D));        \work with a copy of the string
  1043.     if SSTR(I) = ESC then quit;
  1044.     I:= I +1;
  1045.     D:= D +1;
  1046.     end;
  1047.  
  1048. CH1:= SSTR(0);
  1049. if CH1 = ESC then            \Check for null string (no can handle)
  1050.     [SETSTAT("null?",true);   return D];
  1051. if S1F then CH1:= CH1 ! $20;
  1052.  
  1053. if PARAMS(S2FLAG) then BACKSEARCH else FWDSEARCH;
  1054. return D;
  1055. end;    \SEARCH
  1056.  
  1057. \----------------------------------------------------------------------
  1058.  
  1059. proc    INDENT;        \Indent current line same as the preceding one
  1060. int    COL,        \The column number to indent to
  1061.     C,        \temporary index into text buffer
  1062.     TABS, SPS,    \number of tabs and spaces to insert
  1063.     I;        \scratch
  1064. begin
  1065. \Move to the beginning of the previous line:
  1066. if BUFFER(CINX-1) = CR then BACKLINE
  1067. else    [BACKLINE;   BACKLINE];
  1068.  
  1069. \Move the column counter according to the previous line's leading tabs
  1070. \ and spaces. (If the cursor was on the first line in the buffer, then
  1071. \ COL = 0)
  1072. COL:=0;
  1073. if not ERRFLAG then            \it was not on the first line
  1074.     begin                \count the number of columns the
  1075.     C:=C2INX;            \ previous line is indented
  1076.     loop    begin
  1077.         case BUFFER(C) of
  1078.           SP:    COL:= COL + 1;
  1079.           TAB:    [COL:= (COL + 8) & $FFF8]    \move to next tab stop
  1080.         other quit;
  1081.         C:= C+1;
  1082.         end;
  1083.  
  1084.     \Move back to the beginning of the current line
  1085.     FWDLINE;
  1086.     end
  1087. else SETSTAT("ok",false);
  1088.  
  1089. \Delete all initial tabs and spaces on the current line:
  1090. loop    begin
  1091.     case BUFFER(C2INX) of
  1092.       SP, TAB: if C2INX < BUFSIZ then [FWDCHAR;   DELCHAR] else quit
  1093.     other quit;
  1094.     end;
  1095.  
  1096. \Insert tabs and spaces to move to the column determined above
  1097. TABS:= COL/8;
  1098. SPS:= REM(0);
  1099. for I:=1,TABS do INSERT(TAB);
  1100. for I:=1,SPS do INSERT(SP);
  1101. \(leave cursor at the first displayable character)
  1102. end;    \INDENT
  1103.  
  1104.  
  1105.  
  1106. proc    CENTER;        \Center the current line between margins
  1107. int    COL,        \The column number to indent to
  1108.     C,        \temporary index into text buffer
  1109.     TABS, SPS,    \number of tabs and spaces to insert
  1110.     I;        \scratch
  1111. begin
  1112. \Move to the beginning of the line:
  1113. if BUFFER(CINX-1)#CR & CINX>0 then BACKLINE;
  1114.  
  1115. \Delete all initial tabs and spaces on the line:
  1116. loop    begin
  1117.     case BUFFER(C2INX) of
  1118.       SP, TAB: if C2INX < BUFSIZ then [FWDCHAR;   DELCHAR] else quit
  1119.     other quit;
  1120.     end;
  1121.  
  1122. \Count the number of printable characters remaining on the line:
  1123. C:= C2INX;
  1124. COL:= 0;
  1125. loop    begin
  1126.     if BUFFER(C)=CR ! C>=BUFSIZ then quit;
  1127.     if BUFFER(C) >= SP & BUFFER(C) <= $7E then COL:= COL +1;
  1128.     C:= C +1;
  1129.     end;
  1130.  
  1131. \Calculate amount to indent line:
  1132. COL:= (PARAMS(RIGHTMARGIN) -PARAMS(LEFTMARGIN) -COL +1) /2;
  1133.  
  1134. \Insert tabs and spaces:
  1135. TABS:= COL/8;
  1136. SPS:= REM(0);
  1137. for I:=1,TABS do INSERT(TAB);
  1138. for I:=1,SPS do INSERT(SP);
  1139. \(leave cursor at the first displayable character)
  1140. end;    \CENTER
  1141.  
  1142. \----------------------------------------------------------------------
  1143.  
  1144. func    MARGIN(D);    \Re-margin paragraph (or get bell column)
  1145. int    D;        \index to arguments (if any)
  1146. int    LM, RM,        \left & right margin columns
  1147.     BELLFLAG,    \this is a bell set command (not a margin)
  1148.     COL,        \column
  1149.     I,        \scratch
  1150.     TABS,        \number of tabs
  1151.     SPS;        \number of spaces
  1152.  
  1153.  
  1154.     func    NUMIN;
  1155.     \Get positive integer from command line and return its value
  1156.     \Also moves D to the char terminating the number
  1157.     int    NUM, CH;
  1158.     begin
  1159.     NUM:= 0;
  1160.     CH:= DBUF(DN,D);
  1161.     while CH = SP do        \Eat leading spaces
  1162.         begin
  1163.         D:= D+1;
  1164.         CH:= DBUF(DN,D);
  1165.         end;
  1166.     while CH>=^0 & CH<=^9 do
  1167.         begin
  1168.         NUM:= NUM *10 + (CH -^0);
  1169.         if NUM < 0 then [SETSTAT("number?",true);   return 0];
  1170.         D:= D+1;
  1171.         CH:= DBUF(DN,D);
  1172.         end;
  1173.     return NUM;
  1174.     end;    \NUMIN
  1175.  
  1176.  
  1177. begin    \MARGIN
  1178. if DBUF(DN,D)>= ^0 & DBUF(DN,D)<= ^9 ! DBUF(DN,D)=^( then 
  1179.     begin                \we have arguments -- go get 'em
  1180.     if DBUF(DN,D)=^( then D:= D +1;    \parentheses are optional
  1181.     LM:= NUMIN;            \get the new left margin column
  1182.     BELLFLAG:= false;        \assume it is not a bell setting
  1183.     if DBUF(DN,D)=^, ! DBUF(DN,D)=SP then [D:= D +1;   RM:= NUMIN]
  1184.     else BELLFLAG:= true;
  1185.     if DBUF(DN,D)=^, ! DBUF(DN,D)=SP then
  1186.         [D:= D +1;   PARAMS(PARAINDENT):= NUMIN];
  1187.     if DBUF(DN,D)=^) then D:= D +1;    \parentheses are optional
  1188.     if BELLFLAG then        \only one argument means set bell
  1189.         [PARAMS(BELLCOL):= LM;   return D+1];    \ and we're done
  1190.     PARAMS(LEFTMARGIN):= LM;    \set new left and right margin columns
  1191.     PARAMS(RIGHTMARGIN):= RM;
  1192.     end;
  1193.  
  1194. if ERRFLAG then return D;
  1195. if CINX>0 then BACKCHAR;        \(margin back)
  1196.  
  1197. \Move to the end of the paragraph (2 CR's or end of buffer):
  1198. loop    begin
  1199.     if C2INX >= BUFSIZ then quit;
  1200.     if BUFFER(C2INX) = CR then
  1201.         begin
  1202.         FWDCHAR;
  1203.         if BUFFER(C2INX)=CR ! C2INX>=BUFSIZ then
  1204.             [BACKCHAR;   BACKCHAR;   quit];
  1205.         end;
  1206.     FWDCHAR;
  1207.     end;
  1208.     \C2INX points to the last letter of the paragraph
  1209. SETSTAT("ok",false);        \(in case there are 2 CR's at the beginning)
  1210.  
  1211. \Move to the start of the paragraph replacing CR's and tabs with spaces:
  1212. loop    begin
  1213.     if BUFFER(C2INX) = TAB then BUFFER(C2INX):= SP;
  1214.     if BUFFER(C2INX) = CR then
  1215.         begin
  1216.         if CINX<=0 then [FWDCHAR;   quit];
  1217.         BACKCHAR;
  1218.         if BUFFER(C2INX)=CR then [FWDCHAR;   FWDCHAR;   quit];
  1219.         FWDCHAR;
  1220.         BUFFER(C2INX):= SP;
  1221.         end;
  1222.     if CINX<=0 then quit;
  1223.     BACKCHAR;
  1224.     end;
  1225. SETSTAT("ok",false);
  1226.  
  1227. \Move to the end of the paragraph deleting multiple spaces:
  1228. while BUFFER(C2INX) = SP do        \delete any spaces at the beginning
  1229.     [FWDCHAR;   DELCHAR];
  1230. loop    begin
  1231.     if BUFFER(C2INX) = SP then
  1232.         begin
  1233.         FWDCHAR;
  1234.         while BUFFER(C2INX) = SP do
  1235.             [FWDCHAR;   DELCHAR];
  1236.         end;
  1237.     if BUFFER(C2INX)=CR ! C2INX>=BUFSIZ then quit;
  1238.     FWDCHAR;
  1239.     end;
  1240. SETSTAT("ok",false);
  1241.  
  1242. \Move to the start of the paragraph (now only one line long):
  1243. BACKLINE;
  1244. SETSTAT("ok",false);
  1245.  
  1246. COL:= PARAMS(LEFTMARGIN) +PARAMS(PARAINDENT);    \the first line may be indented
  1247. loop    begin
  1248.     \insert tabs and spaces to get to the left margin:
  1249.     TABS:= COL/8;
  1250.     SPS:= REM(0);
  1251.     for I:=1,TABS do INSERT(TAB);
  1252.     for I:=1,SPS do INSERT(SP);
  1253.     INSERT(CR);            \insert a fake CR to mark our place
  1254.     \(This is required if we have a word longer than a line and we are
  1255.     \ are indenting with spaces.)
  1256.  
  1257.     \Move to the right margin +1:
  1258.     loop    begin
  1259.         if COL > PARAMS(RIGHTMARGIN) then quit;
  1260.         FWDCHAR;        \(sets ERRFLAG at end of buffer)
  1261.         if BUFFER(C2INX) = CR ! ERRFLAG then    \all done
  1262.             begin
  1263.             SETSTAT("ok",false);        \in case of ERRFLAG
  1264.             BACKLINE;            \back up to fake CR
  1265.             DELCHAR;            \eat it
  1266.             FWDLINE;            \move to new line
  1267.             FWDCHAR;
  1268.             return D;
  1269.             end;
  1270.  
  1271.         if BUFFER(C2INX) >= $20 & BUFFER(C2INX) <= $7E then
  1272.             COL:= COL +1;    \don't count ctrl chars
  1273.         end;
  1274.  
  1275.     \Move back to previous space and replace it with a CR:
  1276.     loop    begin
  1277.         if BUFFER(C2INX) = SP then
  1278.             [BUFFER(C2INX):= CR;   quit];
  1279.  
  1280.         \Deal with case where a word is longer than a line:
  1281.         if BUFFER(C2INX) = CR then    \(our fake CR)
  1282.             repeat    begin
  1283.                 FWDCHAR;
  1284.                 if BUFFER(C2INX) = SP then
  1285.                     [BUFFER(C2INX):= CR;   quit];
  1286.                 if BUFFER(C2INX) = CR ! ERRFLAG then quit;
  1287.                 end;
  1288.             until false;
  1289.         BACKCHAR;
  1290.         if ERRFLAG then quit;
  1291.         end;
  1292.  
  1293.     if ERRFLAG then quit;
  1294.     BACKLINE;            \back up to fake CR
  1295.     DELCHAR;            \eat it
  1296.     FWDLINE;            \move to new line
  1297.     COL:= PARAMS(LEFTMARGIN);
  1298.     end;
  1299. return D;
  1300. end;    \MARGIN
  1301.  
  1302. \============================ I/O COMMANDS ==============================\
  1303.  
  1304. \WARNING! One or both of the files may be missing ???
  1305. proc    OPENFILES;    \Open the files
  1306. begin
  1307. OPENI(DISK);
  1308. OPENO(DISK);
  1309. EOFFLAG:=false;
  1310. end;    \OPENFILES
  1311.  
  1312.  
  1313.  
  1314. proc    APPEND;        \Append input file to edit buffer
  1315. \(XPL is fast; serial I/O is slow.)
  1316. reg int    CH, LIMIT;
  1317. begin
  1318. LIMIT:= C2INX -PAD;
  1319. if EOFFLAG then
  1320.     SETSTAT("eof?",true)
  1321. else    loop begin
  1322.     if CINX >= LIMIT then        \if we're almost full, then start
  1323.         begin            \ looking for a carriage return
  1324.         if CINX >= C2INX then        \(test before we read)
  1325.             [SETSTAT("full?",true);   quit];
  1326.         CH:= CHIN3;
  1327.         if CH = EOF then
  1328.             [EOFFLAG:= true;   SETSTAT("eof",false);   quit];
  1329.         BUFFER(CINX):= CH;
  1330.         CINX:= CINX+1;
  1331.         if CH = CR then quit;    \stop at the end of a line
  1332.         end
  1333.     else    begin
  1334.         CH:= CHIN3;
  1335.         if CH = EOF then
  1336.             [EOFFLAG:= true;   SETSTAT("eof",false);   quit];
  1337.         BUFFER(CINX):= CH;
  1338.         CINX:= CINX+1;
  1339.         end;
  1340.     end;    \loop
  1341. SAVEPTRS;
  1342. end;    \APPEND
  1343.  
  1344.  
  1345.  
  1346. proc    WRITEBUF;    \Write the edit buffer to the output disk file
  1347. reg int    I;
  1348. begin
  1349. if not CLOSFLAG then
  1350.     begin
  1351.     FWDALL;
  1352.     for I:= 0, CINX-1 do
  1353.         CHOUT3(BUFFER(I));
  1354.     end
  1355. else SETSTAT("closed?",true);
  1356. end;    \WRITEBUF
  1357.  
  1358.  
  1359.  
  1360. proc    NEXTBUF;    \Get next buffer-full (ESC-G)
  1361. begin
  1362. WRITEBUF;
  1363. if not ERRFLAG then
  1364.     begin
  1365.     DELALL;
  1366.     APPEND;
  1367.     end;
  1368. end;    \NEXTBUF
  1369.  
  1370.  
  1371.  
  1372. func    BUFSEARCH(D);    \Forward search N buffers for string
  1373. int    D;
  1374. int    DX, S2F;
  1375. begin
  1376. S2F:= PARAMS(S2FLAG);            \Save current search direction
  1377. PARAMS(S2FLAG):= false;            \Set to forward search
  1378. loop    begin
  1379.     DX:= SEARCH(D);
  1380.     if ERRFLAG then            \We didn't find it in this buffer
  1381.         begin
  1382.         if not EOFFLAG then
  1383.             [SETSTAT("ok",false);    \clear ERRFLAG from search
  1384.             NEXTBUF;
  1385.             SETSTAT("ok",false);    \clear possible eof flag
  1386.             BACKALL]
  1387.         else quit;        \(leaves last buffer in memory)
  1388.         end
  1389.     else quit;            \found it, stop looking
  1390.     end;
  1391. PARAMS(S2FLAG):= S2F;            \Restore search direction
  1392. return DX;                \return index to next command
  1393. end;    \BUFSEARCH
  1394.  
  1395.  
  1396.  
  1397. proc    QUIT;        \Output the buffer and remaining input file to disk
  1398. reg int    CH;
  1399. begin
  1400. if not CLOSFLAG then            \save file to disk
  1401.     begin
  1402.     WRITEBUF;
  1403.  
  1404.     if not EOFFLAG then        \if we haven't encountered an EOF
  1405.         begin            \ shuffle the in file to the out file
  1406.         loop    begin
  1407.             CH:= CHIN3;
  1408.             if CH = EOF then quit;
  1409.             CHOUT3(CH);
  1410.             end;
  1411.         EOFFLAG:= true;            \(in case we don't exit)
  1412.         end;
  1413.  
  1414.     CLOSE(DISK);
  1415.     CLOSFLAG:= true;
  1416.     end;
  1417.  
  1418. CHOUT(0,FF);
  1419. exit;
  1420. end;    \QUIT
  1421.  
  1422. \=========================== MACRO COMMANDS =============================\
  1423.  
  1424. proc    CMD2TXT;    \Copy command line to text buffer
  1425. int    I;
  1426. begin
  1427. for I:= 0, DINX(DN)-1 do
  1428.     INSERT(DBUF(DN,I));
  1429. end;    \CMD2TXT
  1430.  
  1431.  
  1432.  
  1433. proc    TXT2CMD;    \Copy text into command line
  1434. int    C, D;
  1435. begin
  1436. C:=C2INX;
  1437. D:=0;
  1438. loop    begin
  1439.     DBUF(DN,D):= BUFFER(C);
  1440.     C:= C+1;
  1441.     D:= D+1;
  1442.  
  1443.     if D>=2 then if DBUF(DN,D-1)=ESC & DBUF(DN,D-2)=ESC then
  1444.         [DINX(DN):= D;   quit];
  1445.  
  1446.     if C>=BUFSIZ ! D>=DBUFSIZ then
  1447.         [SETSTAT("esc esc?",true);
  1448.         quit];
  1449.     end;
  1450. SHOWCMDLINE;
  1451. end;    \TXT2CMD
  1452.  
  1453.  
  1454.  
  1455. proc    SELCMD;        \Select a command line [0-9]
  1456. int    N;
  1457. begin
  1458. \Get the number of the command line.
  1459. \Move cursor to status line.
  1460. CURL:= HEIGHT -1;   CURH:= 16;
  1461. N:= KEYIN;
  1462. if N>=^0 & N<=^9 then [DN:= N -^0;   SHOWCMDLINE]
  1463. else SETSTAT("number?",true);
  1464. end;    \SELCMD
  1465.  
  1466. \============================ GET COMMANDS ==============================\
  1467.  
  1468. proc    BADCMD;        \Handle unimplemented commands
  1469. SETSTAT("illegal?",true);
  1470.  
  1471.  
  1472.  
  1473. proc    DOIMMCMD(CH);    \Execute an immediate command (control character)
  1474. int    CH;        \ or insert the text character (CH)
  1475. begin
  1476. case CH of
  1477.  CTRLA:    FWDCHAR;
  1478.  CTRLB:    BACKWORD;
  1479.  CTRLC:    DELWORD;
  1480.  CTRLD:    FWDALL;
  1481.  CTRLE:    BACKALL;
  1482.  CTRLF:    XOFF;
  1483.  CTRLG:    SETSTAT("use J?",true);        \(recursion may overflow stack)
  1484.  CTRLH, DEL: DELCHAR;
  1485. \CTRLI is a TAB
  1486.  CTRLJ:    FWDPAGE;
  1487.  CTRLK:    BACKPAGE;
  1488. \CTRLL is a FF
  1489. \CTRLM is a CR
  1490.  CTRLN:    FWDWORD;
  1491.  CTRLO:    OOPS;
  1492.  CTRLP:    SELCMD;
  1493.  CTRLQ:    BACKCHAR;
  1494.  CTRLR:    XON;
  1495.  CTRLS:    FWDLINE;
  1496.  CTRLT:    PARAMS(SHOWFLAG):= not PARAMS(SHOWFLAG);
  1497.  CTRLU:    INDENT;
  1498.  CTRLV:    CMD2TXT;
  1499.  CTRLW:    BACKLINE;
  1500.  CTRLX:    DELLINE;
  1501.  CTRLY:    [COPYX;   XINX:=0];
  1502.  CTRLZ:    FLIPCASE;
  1503. \CTRL@\$00: INSERT(SP);            \(because of the damn Wyse terminal)
  1504. \CTRL[ IS AN ESC
  1505. \CTRL\ $1C: BADCMD;        \SWAPCURSORS;
  1506. \CTRL]\$1D: PARAMS(S1FLAG):= not PARAMS(S1FLAG);
  1507. \CTRL^\$1E: INSERT(KEYIN);        \insert next character literally
  1508. \CTRL_\$1F: PARAMS(S2FLAG):= not PARAMS(S2FLAG)
  1509. other INSERT(CHAR);
  1510. end;    \DOIMMCMD
  1511.  
  1512. \----------------------------------------------------------------------
  1513.  
  1514. proc    DOCMDLINE;    \Execute a deferred command (from the command line)
  1515. int    I, J, CH,
  1516.     D,        \index into command line buffer (DBUF)
  1517.     DX,        \index pointer to next command
  1518.     COUNT;        \repeat count
  1519.             \Note that groups of commands may be repeated, each
  1520.             \ group is separated by an ESC.
  1521.  
  1522.  
  1523.     proc    CALLCMD;    \call a command line (recursive)
  1524.     int    CMD, SDN;
  1525.     begin
  1526.     CMD:= DBUF(DN,D+1) -^0;        \get the command-line number
  1527.     if CMD>=0 & CMD<=9 then
  1528.         begin
  1529.         SDN:= DN;        \save current command line
  1530.         DN:= CMD;        \execute called command line
  1531.         DOCMDLINE;
  1532.         SETSTAT("ok", false);    \don't stop now
  1533.         DN:= SDN;        \resume current command line
  1534.         end
  1535.     else    SETSTAT("number?", true);
  1536.     DX:= D +1;            \skip the command-line number
  1537.     end;    \CALLCMD
  1538.  
  1539.  
  1540. begin    \DOCMDLINE
  1541. D:= 0;
  1542. loop    begin                \loop over all chars in cmd line
  1543.     if D >= DINX(DN) then quit;
  1544.     CH:= DBUF(DN,D);
  1545.  
  1546.     COUNT:= 0;
  1547.     while CH>=^0 & CH<=^9 do    \get repeat count
  1548.         begin
  1549.         COUNT:= COUNT *10 + (CH -^0);
  1550.         if COUNT < 0 then [SETSTAT("number?",true);   quit];
  1551.         D:= D+1;
  1552.         CH:= DBUF(DN,D);
  1553.         end;
  1554.     if COUNT <1 then COUNT:= 1;    \do it at least once
  1555.  
  1556.     if CH>=^a & CH<=^z then        \convert to uppercase
  1557.         CH:= CH-$20;
  1558.  
  1559.     DX:= D +1;            \assume a one-char command
  1560.  
  1561.     \Execute the command COUNT number of times:
  1562.     for I:= 1,COUNT do
  1563.         begin
  1564.         if (CH<$20 & CH#ESC) ! CH=$7F then DOIMMCMD(CH)
  1565.         else
  1566.         case CH of
  1567.           ^A:    APPEND;            \DEFERRED COMMANDS
  1568.           ^B:    BADCMD;            \DELLINE; (can insert CTRL-X)
  1569.           ^C:    [CLOSE(DISK);   CLOSFLAG:= true];
  1570.           ^D:    DELCHAR;        \(inserting DEL is awkward)
  1571.           ^E:    XINX:= 0;        \empty scoop
  1572.           ^F:    BADCMD;        \[FWDCHAR; if not ERRFLAG then DELCHAR];
  1573.           ^G:    NEXTBUF;        \read next text buffer
  1574.           ^H:    DX:= INHEX(D+1);    \insert literal hex
  1575.           ^I:    DX:= INSTRING(D+1);    \insert string
  1576.           ^J:    DX:= 0;            \restart command line
  1577.           ^K:    DELALL;            \kill entire buffer
  1578.           ^L:    LIST;            \list on printer
  1579.           ^M:    DX:= MARGIN(D+1);    \remargin
  1580.           ^N:    DX:= BUFSEARCH(D+1);    \search "N" buffers
  1581.           ^O:    OPENFILES;
  1582.           ^P:    CALLCMD;        \call another command line
  1583.           ^Q:    QUIT;            \save file and return to Apex
  1584.           ^R:    DELREST;        \delete the rest of a line
  1585.           ^S:    DX:= SEARCH(D+1);    \search for string
  1586.           ^T:    [CHOUT(0,FF);   ABORT];    \terminate & save memory image
  1587.           ^U:    BADCMD;
  1588.           ^V:    [TXT2CMD;   quit];    \text to command line
  1589.           ^W:    WRITEBUF;        \write edit buffer to disk
  1590.           ^X:    COPYX;            \copy scoop (X register)
  1591.           ^Y:    CENTER;
  1592.           ^Z:    ZAP;            \delete back to form feed
  1593.           ^?:    [HELP(0); SHOWCMDLINE];    \show help messages
  1594.           ^/:    HELP(2);        \print help messages
  1595.           SP:    [];            \inert space (for readability)
  1596.           ESC:    []            \(command separator)
  1597.         other BADCMD;
  1598.  
  1599.         if ERRFLAG then quit;
  1600.         end;    \for loop
  1601.  
  1602.     D:= DX;                \point to next command in line buffer
  1603.     end;    \loop
  1604. end;    \DOCMDLINE
  1605.  
  1606. \----------------------------------------------------------------------
  1607.  
  1608. proc    ENTERCMDLINE;    \Enter and execute a command line
  1609. int    CH, SDINX;
  1610. begin
  1611. DBUF(DN,0):= ESC;            \store and echo the escape key
  1612. DINX(DN):= 1;
  1613. SDINX:= 0;
  1614.  
  1615. \Display a temporary cursor in the body of the text:
  1616. CURSOR(if CURH<WIDTH then CURH else WIDTH-1, CURL);
  1617. CHOUT(0,$7F);                \ %%%
  1618. SHOWCMDLINE;                \show ESC and cleared command line
  1619.                     \this also sets the cursor position
  1620. repeat    begin
  1621.     CH:= KEYIN;
  1622.     case CH of
  1623.      DEL, CTRLH:
  1624.         if DINX(DN) > 0 then DINX(DN):= DINX(DN) -1;
  1625.  
  1626.      CTRLX: DINX(DN):= 0;
  1627.  
  1628.      CTRLO:    if SDINX = 0 then
  1629.             begin        \OOPS! Undelete command line
  1630.             SDINX:= DINX(DN);
  1631.             DINX(DN):= 0;        \move forward until esc, esc
  1632.             repeat DINX(DN):= DINX(DN) +1;
  1633.             until (DBUF(DN,DINX(DN)-1) =ESC &
  1634.                 DBUF(DN,DINX(DN)) =ESC) ! DINX(DN) >=DBUFSIZ;
  1635.             end
  1636.         else    begin        \put things back (toggle CTRL-O)
  1637.             DINX(DN):= SDINX;
  1638.             SDINX:= 0;
  1639.             end;
  1640.       \CTRL^\$1E:
  1641.         begin            \Literal insert
  1642.         CH:= KEYIN;
  1643.         if DINX(DN) < DBUFSIZ then
  1644.             [DBUF(DN,DINX(DN)):= CH;   DINX(DN):= DINX(DN) +1]
  1645.         else SETSTAT("length?",true);    \(do not exit loop!)
  1646.         end
  1647.     other    begin
  1648.         if DINX(DN) < DBUFSIZ then
  1649.             [DBUF(DN,DINX(DN)):= CH;   DINX(DN):= DINX(DN) +1]
  1650.         else SETSTAT("length?",true);    \(do not exit loop!)
  1651.         end;
  1652.     SHOWCMDLINE;
  1653.     end;
  1654. until (CH=ESC & DBUF(DN,DINX(DN)-2)=ESC) ! DINX(DN)=0;    \ESC ESC or empty
  1655.  
  1656. DOCMDLINE;
  1657. end;    \ENTERCMDLINE
  1658.  
  1659. \----------------------------------------------------------------------
  1660.  
  1661. proc    INITIALIZE;    \First-time (cold-start) initialization
  1662. int    I,J;
  1663. addr    STR;
  1664. begin
  1665. CINX:=0;                \empty main buffer
  1666. C2INX:= BUFSIZ;
  1667. SAVEPTRS;
  1668. XINX:= 0;                \empty X buffer (register)
  1669. XFLAG:= false;
  1670.  
  1671. EOFFLAG:= false;
  1672. SETSTAT("ok",false);            \init status display and ERRFLAG
  1673.  
  1674. CURLINE:= (HEIGHT -6);            \put cursor on 3rd line from bottom
  1675. CURH:=0;   CURL:=CURLINE;        \init cursor position
  1676.  
  1677. \Put starting message in command buffer and display it while we wait:
  1678. \ (Note that <ESC>- will not execute.)
  1679. STR:="    -- ED, Version 1.1 --                     For help type: <ESC>?<ESC><ESC>";
  1680. for DN:=0,9 do                \init empty (esc, esc is for OOPS)
  1681.     begin
  1682.     DINX(DN):= 0;
  1683.     for I:=0,DBUFSIZ-1 do
  1684.         DBUF(DN,I):= ESC;
  1685.     end;
  1686. DN:= 0;
  1687. I:= 0;
  1688. repeat    DBUF(DN,I):= STR(I);
  1689.     I:= I +1;
  1690. until STR(I) = 0;            \Note that the string will not execute
  1691. DINX(DN):= I;
  1692. CHOUT(0,FF);
  1693. SHOWCMDLINE;
  1694.  
  1695. \Set up ruler display:
  1696. for I:= 0,COLMAX do TICKMARKS(I):= ^-;
  1697. for I:= 5,COLMAX do [TICKMARKS(I):= ^+;   I:= I+9];
  1698. J:= ^0;
  1699. for I:= 0,COLMAX do
  1700.     [TICKMARKS(I):= J;
  1701.     J:= J+1;
  1702.     if J = ^: then J:=^A;
  1703.     I:= I+9];
  1704.  
  1705. OPENFILES;
  1706. APPEND;
  1707.  
  1708. PARAMS(COLDFLAG):= false;        \indicate we're initialized
  1709. end;    \INITIALIZE
  1710.  
  1711. \----------------------------------------------------------------------
  1712.  
  1713. begin    \MAIN
  1714. \The "+4 +4" trick prevents the RESERVE argument from changing the array
  1715. \ contents in case this is a restart.
  1716. XBUF:= RESERVE(XBUFSIZ +4) +4;        \reserve all the arrays here
  1717. DINX:= RESERVE(10*4 +4) +4;
  1718. DBUF:= RESERVE(10*4 +4) +4;
  1719. for II:= 0,9 do DBUF(II):= RESERVE(DBUFSIZ*4 +4) +4;
  1720. TICKMARKS:= RESERVE(COLMAX+1 +4) +4;
  1721. SSTR:= RESERVE(DBUFSIZ +4) +4;
  1722. BUFSIZ:= FREE - 2000;
  1723. BUFSIZ:= BUFSIZ - REM(BUFSIZ/1000);    \round down to even 1000
  1724. BUFFER:= RESERVE(BUFSIZ +4) +4;
  1725.  
  1726. ADDR:= 0;   ADDR(CHKUSRF):= 0;        \disable CTRL-C = abort, etc.
  1727.                     \ re-enabled by OPENI(0)
  1728. HEIGHT:= ADDR(CONHIGH);
  1729. WIDTH:= ADDR(CONWIDE);
  1730.  
  1731. CLOSFLAG:= false;        \(ED can be restarted with a new output file)
  1732.  
  1733. PARAMS:= [true, 0, 72, 72, 0, false, false, false];
  1734. \[COLDFLAG, LEFTMARGIN, RIGHTMARGIN, BELLCOL, PARAINDENT, S1FLAG, S2FLAG, SHOWFLAG]
  1735. if PARAMS(COLDFLAG) then INITIALIZE    \is this a restart?
  1736. else [CHOUT(0,FF);   SHOWCMDLINE];
  1737.  
  1738. loop    begin
  1739.     DISPLAY;            \display the text
  1740.     CHAR:= KEYIN;            \wait for key if not already struck
  1741.     SETSTAT(if XFLAG then "scoop" else "ok",false);    \init status display
  1742.     if CHAR = ESC then ENTERCMDLINE    \enter and execute a command line 
  1743.     else if CHAR = CTRLG then DOCMDLINE \(not allowed in deferred mode)
  1744.     else DOIMMCMD(CHAR);        \do immediate command or insert char
  1745.     end;
  1746. end;    \MAIN
  1747. hen DOCMDLINE \(not al